* Written for WLS data release 13.01 
* 12/12/2013 - Kamil Sicinski

program define wls2stata

version 12

syntax varlist [, VARName(string) VARLabel(string) VALUelabel(string) NORecode(varlist) skipstring]


local miscode1=".d" //Don't know 
local miscode2=".i" //Inappropriate 
local miscode3=".r" //Refused 
local miscode4=".n" //Not ascertained 
local miscode5=".p" //Partial interview 
local miscode11=".a" //At most part time worker 
local miscode12=".c" //At least full time worker 
local miscode13=".e" //Amount Differs For Generic/Brand-Name 
local miscode14=".f" //Amount Changes Over The Year (Vol) 
local miscode15=".g" //Multiple Sessions 
local miscode16=".h" //Never went to usual provider 
local miscode17=".j" //Special Missing Code for Allocation Cases 
local miscode18=".k" //Unable to Code (ICD-9 related questions) 
local miscode19=".l" //Occupational scores not assigned to military occupations 
local miscode20=".o" //Amt varies 
local miscode21=".q" //Pays all costs not covered by the plan 
local miscode22=".u" //Different payment arrangement 
local miscode23=".v" //Attended a HS in Wisconsin, did not graduate from that HS  
local miscode24=".w" //Volunteered, < 1 drink per day 
local miscode25=".x" //Only drank at religious services 
local miscode26=".y" //Unable to code, multiple people mentioned 
local miscode27=".s" //Not asked of Proxy 
local miscode28=".t" //Not asked via telephone 
local miscode29=".b" //Left Blank on SAQ 
local miscode30=".m" //Not part of MOSAQ 
local miscode31=".z" //Still not assigned?

** ISSUE: The number of negative codes exceeds the number of Stata missing codes
** SOLUTION: Codes -6 though -10 are NOT recoded as missing


** ISSUE: some imputations fall into the missing codes range, yet need to be recoded because of inap and partial interview codes
** SOLUTION: make a special list and recode only those two missing codes
local negimplist sr033rei1 cr035rpci1 cr031rpci2 cr035rpci2 cr035rpci3 gr035rpci5 gr100rpci5 cr035rpci5


** ISSUE: a hard-coded list will not work if the variables are upper case or proper case
** SOLUTION: make 3 versions of fullskiplist, add them together and use this list to construct newvarlist
local loskiplist maxscore max_fcoder max_mcoder meanrat meanrat_trunc meanrat_fcoder meanrat_mcoder minscore min_fcoder min_mcoder srbmi ///
normscore1 normscore2 normscore3 normscore4 normscore5 normscore6 normscore7 normscore8 normscore9 normscore10 normscore11 normscore12  

foreach ele in `loskiplist' {
local temp=upper("`ele'")
local upskiplist `upskiplist' `temp'

local temp=proper("`ele'")
local prskiplist `prskiplist' `temp'
}
local fullskiplist : list loskiplist | upskiplist 
local fullskiplist : list fullskiplist | prskiplist 
local fullskiplist : list fullskiplist | norecode

local recodevarlist : list varlist - fullskiplist

foreach ele in `negimplist' {
local temp=upper("`ele'")
local upimplist `upimplist' `temp'

local temp=proper("`ele'")
local primplist `primplist' `temp'
}
local fullnegimplist : list negimplist | upimplist 
local fullnegimplist : list fullnegimplist | primplist 

local recodevarlist : list recodevarlist - fullnegimplist

local reclistsize : list sizeof recodevarlist

***This part of the code loops over each variable from recodevarlist

foreach member of varlist `recodevarlist' {

local reclistpos : list posof "`member'" in recodevarlist
if mod(`reclistpos',max(1,int(`reclistsize'/100),min(5,int(`reclistsize'/10))))==0 di as text "Processing missing codes and value labels for variable: " as res `reclistpos' as text " of " as res `reclistsize' 

** make all variable labels lowercase/uppercase/proper case
local varlab : variable label `member'

if "`varlabel'" == "upper" local newlab = upper(`"`varlab'"')
if "`varlabel'" == "lower" local newlab = lower(`"`varlab'"')
if "`varlabel'" == "proper" local newlab = proper(`"`varlab'"')

if `"`newlab'"'!="" label var `member' `"`newlab'"'

** set missing codes in text variables to empty string

          capture confirm string variable `member'
	  local notstring= _rc

          if `notstring'==0 & "`skipstring'" != "skipstring" {
            qui replace `member' = "" if (`member' == "-1") | (`member' == "-2") | (`member' == "-3") ///
            | (`member' == "-4") | (`member' == "-5") | (`member' == "-6") ///           
            | (`member' == "-7") | (`member' == "-8") | (`member' == "-9") ///           
            | (`member' == "-10") | (`member' == "-11") | (`member' == "-12") ///           
            | (`member' == "-13") | (`member' == "-14") | (`member' == "-15") ///           
            | (`member' == "-16") | (`member' == "-17") | (`member' == "-18") ///           
            | (`member' == "-19") | (`member' == "-20") | (`member' == "-21") ///  
            | (`member' == "-22") | (`member' == "-23") | (`member' == "-24") /// 
            | (`member' == "-25") | (`member' == "-26") | (`member' == "-27") ///
            | (`member' == "-28") | (`member' == "-29") | (`member' == "-30") ///
            | (`member' == "-31")
            }

** copy value labels onto the missing codes of numeric variables
if `notstring'!=0 {
	local vallab : value label `member'
	qui levelsof `member' if `member'>=-31 & `member'<0,local(levels)

	if "`vallab'" != ""  {
	
		foreach value of local levels {       
			local singlelab : label `vallab' `value'
			if `"`singlelab'"' != "`value'" {
				if "`valuelabel'" == "upper" { 
					local newsinglelab = upper(`"`singlelab'"')
				}			
				else if "`valuelabel'" == "lower" {
					local newsinglelab = lower(`"`singlelab'"')
				}
				else if "`valuelabel'" == "proper" {
					local newsinglelab = proper(`"`singlelab'"')
				}
		        	else local newsinglelab = `"`singlelab'"'
	
				local avalue=abs(`value')
				if `avalue'==6 | `avalue'==7 | `avalue'==8 | `avalue'==9 | `avalue'==10   {
					label define `vallab' `value' `"`newsinglelab'"' , modify			
				}	
				else	label define `vallab' `value' "" `miscode`avalue'' `"`newsinglelab'"' , modify 
	                }
	        }
	
		** Figure out the looping range
		qui levelsof `member' if `member'>=0,local(plevels)	
		scalar skip=0	//will change to 1 and skip foreach loop if scalar is 1
		
		*Skip if too many levels
		local listsize : list sizeof plevels
		if `listsize'>100 scalar skip=1

		* Skip for float variables? 	
		local vartype : type `member'
		if "`vartype'"=="float" scalar skip=1

		*Skip if VALUelabel option not specified
		if "`valuelabel'"=="" scalar skip=1
	
		//if skip==1 di as text "       Variable " as result "`member'  SKIPPED" as text " for value label recode"			

		if skip==0 {
			foreach value of local plevels {       
				local singlelab : label `vallab' `value'

				if `"`singlelab'"' != "`value'" {
					if "`valuelabel'" == "upper" { 
						local newsinglelab = upper(`"`singlelab'"')
					}			
					else if "`valuelabel'" == "lower" {
						local newsinglelab = lower(`"`singlelab'"')
					}
					else if "`valuelabel'" == "proper" {
						local newsinglelab = proper(`"`singlelab'"')
					}
			        	else local newsinglelab = `"`singlelab'"'
				        label define `vallab' `value' `"`newsinglelab'"' , modify 
		                }
		        }
		}
	}
**Recode numeric values to Stata missing codes
quietly mvdecode `member', mv(-1=.d\ -2=.i\ -3=.r\ -4=.n\ -5=.p\ -27=.s\ -28=.t\ -29=.b\ -30=.m\ ///
-11=.a\ -12=.c\ -13=.e\ -14=.f\ -15=.g\ -16=.h\ -17=.j\ -18=.k\ -19=.l\ -20=.o\ -21=.q\ ///
-22=.u\ -23=.v\ -24=.w\ -25=.x\ -26=.y\ -31=.z)

*CHECK how mvdecode handles double and float variables to make sure we don't have the "-1 is not really -1" problem
*All looks fine

} //  ends the "if `notstring'!=0" block

} // end the "foreach member of varlist `recodevarlist'" loop
di ""

*** Change the case of variable labels of variables that are not part of recodevarlist
local labellist : list varlist - recodevarlist
local labellistsize : list sizeof labellist

if `labellistsize'>0 {
	foreach member of varlist `labellist' {
	
	** make all variable labels lowercase/uppercase/proper case
	local varlab : variable label `member'
	
	if "`varlabel'" == "upper" local newlab = upper(`"`varlab'"')
	if "`varlabel'" == "lower" local newlab = lower(`"`varlab'"')
	if "`varlabel'" == "proper" local newlab = proper(`"`varlab'"')
	
	if `"`newlab'"'!="" label var `member' `"`newlab'"'
	}
}


***Recode imputations with values falling into the missing codes range
foreach var in `fullnegimplist' {
	capture confirm new variable `var'
	if _rc!=0 {
		quietly mvdecode `var', mv(-2=.i\ -5=.p)
	}
}

***Rename variables as specified in the varname option
        if "`varname'" == "upper" quietly rename `varlist', upper

        if "`varname'" == "lower" quietly rename `varlist', lower

        if "`varname'" == "proper" quietly rename `varlist', proper


***Special treatment of problem variables
capture replace normscore12=.n if normscore12==-50
capture replace NORMSCORE12=.n if NORMSCORE12==-50
capture replace Normscore12=.n if Normscore12==-50


di ""
di as result "Done"

end
